function People(name) {
  this.name = name
  this.sleep = function() {
    console.log(`${this.name}正在睡觉`)
  }
}

//原型方法
People.prototype.eat = function(food){
  console.log(this.name + '正在吃：' + food);
}

/**
 * 1、原型链继承
 * 优势：简单易于实现，父类新增的实例与属性子类都能访问到
 * 缺点：无法实现多继承；创建子类实例时，不能向父类构造函数中传参数；可以在子类中增加实例属性，如果要新增加原型属性和方法需要在new 父类构造函数的后面
 */

function Woman() {}

Woman.prototype = new People()
Woman.prototype.name = "woman1_mary"

let woman1 = new Woman()
woman1.eat("西瓜")
woman1.sleep()


/**
 * 借用构造函数继承（伪造对象、经典继承）
 * 优点：解决了子类构造函数向父类构造函数中传递参数；可以实现多继承
 * 缺点：方法都在构造函数中定义，无法复用；不能继承原型属性/方法，只能继承父类的实例属性和方法
 */

function Man1(name) {
  //继承了People
  People.call(this); //People.call(this，'wangxiaoxia'); 
  this.name = name || ''
}

let man2 = new Man1("man2_yang");
man2.sleep()
// man2.eat("辣条") 会失败 不能继承原型属性/方法

/**
 * 实例继承（原型式继承）
 * 优势：不限制调用方式；简单，易实现
 * 缺点：不能多次继承
 */

function Man(name) {
  let instance = new People()
  instance.name = name || ''
  return instance
}

let man1 = new Man('man_Bob')

man1.eat("西瓜")
man1.sleep()


/**
 * 组合式继承: 调用父类构造函数，继承父类的属性，通过将父类实例作为子类原型，实现函数复用
 * 优点：函数可以复用；不存在引用属性问题；可以继承属性和方法，并且可以继承原型的属性和方法
 * 缺点：由于调用了两次父类，所以产生了两份实例
 */

function Animal(type, name) {
  this.type = type
  this.name = name
}

Animal.prototype.sleep = function() {
  console.log(this.type + "动物 " + this.name + " 正在睡觉")
}

function Cat(type, name) {
  Animal.call(this, type, name)
}

Cat.prototype = new Animal()
Cat.prototype.constructor = Cat

let cat1 = new Cat('爬行类', "喵喵")
cat1.sleep()


/**
 * ES6继承的方式
 * 
 */

 class People1{
  constructor(name='wang',age='27'){
    this.name = name;
    this.age = age;
  }
  eat(){
    console.log(`${this.name} ${this.age} eat food`)
  }
}
//继承父类
class Woman1 extends People1{ 
   constructor(name = 'ren',age = '27'){ 
     //继承父类属性
     super(name, age); 
   } 
    eat(){ 
     //继承父类方法
      super.eat() 
    } 
} 
let wonmanObj = new Woman1('xiaoxiami'); 
wonmanObj.eat();